package com.deepwiki.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Stream;

/**
 * 项目分类器服务 - 智能检测项目类型
 */
@Service
public class ProjectClassifierService {

    private static final Logger logger = LoggerFactory.getLogger(ProjectClassifierService.class);

    /**
     * 检测项目类型
     *
     * @param repositoryPath 仓库路径
     * @return 项目类型
     */
    public String classifyProject(String repositoryPath) {
        try {
            Path repoPath = Paths.get(repositoryPath);
            if (!Files.exists(repoPath)) {
                logger.warn("仓库路径不存在: {}", repositoryPath);
                return "application";
            }

            // 收集项目特征
            ProjectFeatures features = analyzeProjectFeatures(repoPath);
            
            // 基于特征分类
            return classifyByFeatures(features);
            
        } catch (Exception e) {
            logger.error("项目分类失败: {}", repositoryPath, e);
            return "application"; // 默认类型
        }
    }

    /**
     * 分析项目特征
     */
    private ProjectFeatures analyzeProjectFeatures(Path repoPath) throws IOException {
        ProjectFeatures features = new ProjectFeatures();
        
        // 分析根目录文件
        analyzeRootFiles(repoPath, features);
        
        // 分析目录结构
        analyzeDirectoryStructure(repoPath, features);
        
        // 分析包管理文件
        analyzePackageFiles(repoPath, features);
        
        // 分析代码文件类型分布
        analyzeCodeFiles(repoPath, features);
        
        return features;
    }

    /**
     * 分析根目录文件
     */
    private void analyzeRootFiles(Path repoPath, ProjectFeatures features) throws IOException {
        try (Stream<Path> files = Files.list(repoPath)) {
            files.filter(Files::isRegularFile)
                 .forEach(file -> {
                     String fileName = file.getFileName().toString().toLowerCase();
                     
                     // CLI工具特征
                     if (fileName.equals("cli.js") || fileName.equals("bin.js") || 
                         fileName.equals("index.js") && hasShebang(file)) {
                         features.cliIndicators++;
                     }
                     
                     // 库特征
                     if (fileName.equals("index.js") || fileName.equals("index.ts") || 
                         fileName.equals("lib.js") || fileName.equals("main.js")) {
                         features.libraryIndicators++;
                     }
                     
                     // DevOps特征
                     if (fileName.equals("dockerfile") || fileName.equals("docker-compose.yml") ||
                         fileName.equals("docker-compose.yaml") || fileName.equals("jenkinsfile") ||
                         fileName.equals("gitlab-ci.yml") || fileName.equals(".travis.yml")) {
                         features.devopsIndicators++;
                     }
                     
                     // 开发工具特征
                     if (fileName.equals("webpack.config.js") || fileName.equals("vite.config.js") ||
                         fileName.equals("rollup.config.js") || fileName.equals("gulpfile.js") ||
                         fileName.equals("gruntfile.js")) {
                         features.developmentToolIndicators++;
                     }
                     
                     // 文档项目特征
                     if (fileName.equals("_config.yml") || fileName.equals("mkdocs.yml") ||
                         fileName.equals("gitbook.json") || fileName.equals("docusaurus.config.js")) {
                         features.documentationIndicators++;
                     }
                 });
        }
    }

    /**
     * 分析目录结构
     */
    private void analyzeDirectoryStructure(Path repoPath, ProjectFeatures features) throws IOException {
        try (Stream<Path> dirs = Files.list(repoPath)) {
            dirs.filter(Files::isDirectory)
                .forEach(dir -> {
                    String dirName = dir.getFileName().toString().toLowerCase();
                    
                    // CLI工具目录
                    if (dirName.equals("bin") || dirName.equals("cli") || dirName.equals("commands")) {
                        features.cliIndicators++;
                    }
                    
                    // 库目录
                    if (dirName.equals("lib") || dirName.equals("src") && hasLibraryStructure(dir)) {
                        features.libraryIndicators++;
                    }
                    
                    // 应用目录
                    if (dirName.equals("app") || dirName.equals("pages") || dirName.equals("components") ||
                        dirName.equals("views") || dirName.equals("controllers")) {
                        features.applicationIndicators++;
                    }
                    
                    // DevOps目录
                    if (dirName.equals("deploy") || dirName.equals("k8s") || dirName.equals("kubernetes") ||
                        dirName.equals("helm") || dirName.equals("terraform") || dirName.equals("ansible") ||
                        dirName.equals("docker") || dirName.equals(".github")) {
                        features.devopsIndicators++;
                    }
                    
                    // 开发工具目录
                    if (dirName.equals("tools") || dirName.equals("scripts") || dirName.equals("build") ||
                        dirName.equals("config") || dirName.equals("webpack")) {
                        features.developmentToolIndicators++;
                    }
                    
                    // 文档目录
                    if (dirName.equals("docs") || dirName.equals("documentation") || dirName.equals("wiki") ||
                        dirName.equals("_posts") || dirName.equals("content")) {
                        features.documentationIndicators++;
                    }
                });
        }
    }

    /**
     * 分析包管理文件
     */
    private void analyzePackageFiles(Path repoPath, ProjectFeatures features) {
        // package.json分析
        Path packageJson = repoPath.resolve("package.json");
        if (Files.exists(packageJson)) {
            analyzePackageJson(packageJson, features);
        }
        
        // 其他包管理文件
        if (Files.exists(repoPath.resolve("setup.py"))) {
            features.libraryIndicators++;
        }
        
        if (Files.exists(repoPath.resolve("Cargo.toml"))) {
            features.libraryIndicators++;
        }
        
        if (Files.exists(repoPath.resolve("go.mod"))) {
            String goModContent = readFileContent(repoPath.resolve("go.mod"));
            if (goModContent.contains("main")) {
                features.applicationIndicators++;
            } else {
                features.libraryIndicators++;
            }
        }
    }

    /**
     * 分析package.json
     */
    private void analyzePackageJson(Path packageJson, ProjectFeatures features) {
        try {
            String content = Files.readString(packageJson);
            
            // CLI特征
            if (content.contains("\"bin\"") || content.contains("#!/usr/bin/env")) {
                features.cliIndicators += 2;
            }
            
            // 库特征
            if (content.contains("\"main\"") && !content.contains("\"scripts\"")) {
                features.libraryIndicators++;
            }
            
            // 应用特征
            if (content.contains("react") || content.contains("vue") || content.contains("angular") ||
                content.contains("express") || content.contains("koa") || content.contains("fastify")) {
                features.applicationIndicators++;
            }
            
            // 开发工具特征
            if (content.contains("webpack") || content.contains("babel") || content.contains("eslint") ||
                content.contains("typescript") || content.contains("rollup") || content.contains("vite")) {
                features.developmentToolIndicators++;
            }
            
            // DevOps特征
            if (content.contains("docker") || content.contains("kubernetes") || content.contains("terraform") ||
                content.contains("deployment") || content.contains("ci") || content.contains("cd")) {
                features.devopsIndicators++;
            }
            
        } catch (IOException e) {
            logger.warn("读取package.json失败: {}", packageJson, e);
        }
    }

    /**
     * 分析代码文件类型分布
     */
    private void analyzeCodeFiles(Path repoPath, ProjectFeatures features) {
        try (Stream<Path> files = Files.walk(repoPath, 3)) {
            files.filter(Files::isRegularFile)
                 .forEach(file -> {
                     String fileName = file.getFileName().toString().toLowerCase();
                     String extension = getFileExtension(fileName);
                     
                     // 统计文件类型
                     features.fileTypes.merge(extension, 1, Integer::sum);
                     
                     // CLI工具特征（可执行文件）
                     if (fileName.contains("cli") || fileName.contains("command") || 
                         fileName.contains("bin") && (extension.equals("js") || extension.equals("ts"))) {
                         features.cliIndicators++;
                     }
                     
                     // 配置文件特征
                     if (extension.equals("yml") || extension.equals("yaml") || extension.equals("json") ||
                         extension.equals("toml") || extension.equals("ini")) {
                         features.configFileCount++;
                     }
                 });
        } catch (IOException e) {
            logger.warn("分析代码文件失败: {}", repoPath, e);
        }
    }

    /**
     * 基于特征分类
     */
    private String classifyByFeatures(ProjectFeatures features) {
        // 计算各类型得分
        Map<String, Integer> scores = new HashMap<>();
        scores.put("cli", features.cliIndicators);
        scores.put("library", features.libraryIndicators);
        scores.put("application", features.applicationIndicators);
        scores.put("devops", features.devopsIndicators);
        scores.put("development-tool", features.developmentToolIndicators);
        scores.put("documentation", features.documentationIndicators);
        
        // 特殊规则调整
        applySpecialRules(features, scores);
        
        // 选择得分最高的类型
        return scores.entrySet().stream()
                    .max(Map.Entry.comparingByValue())
                    .map(Map.Entry::getKey)
                    .orElse("application");
    }

    /**
     * 应用特殊分类规则
     */
    private void applySpecialRules(ProjectFeatures features, Map<String, Integer> scores) {
        // 如果配置文件很多，可能是DevOps项目
        if (features.configFileCount > 10) {
            scores.merge("devops", 2, Integer::sum);
        }
        
        // 如果主要是文档文件，可能是文档项目
        int totalFiles = features.fileTypes.values().stream().mapToInt(Integer::intValue).sum();
        int docFiles = features.fileTypes.getOrDefault("md", 0) + 
                      features.fileTypes.getOrDefault("rst", 0) +
                      features.fileTypes.getOrDefault("txt", 0);
        
        if (totalFiles > 0 && (double) docFiles / totalFiles > 0.6) {
            scores.merge("documentation", 3, Integer::sum);
        }
        
        // 如果没有明显特征，根据文件类型判断
        int maxScore = scores.values().stream().mapToInt(Integer::intValue).max().orElse(0);
        if (maxScore <= 1) {
            // 基于主要编程语言判断
            String mainLanguage = features.fileTypes.entrySet().stream()
                    .filter(e -> isCodeExtension(e.getKey()))
                    .max(Map.Entry.comparingByValue())
                    .map(Map.Entry::getKey)
                    .orElse("");
            
            if (mainLanguage.equals("js") || mainLanguage.equals("ts")) {
                // JavaScript/TypeScript项目，需要进一步判断
                if (features.fileTypes.containsKey("html") || features.fileTypes.containsKey("css")) {
                    scores.put("application", 2);
                } else {
                    scores.put("library", 1);
                }
            }
        }
    }

    /**
     * 辅助方法
     */
    private boolean hasShebang(Path file) {
        try {
            String firstLine = Files.lines(file).findFirst().orElse("");
            return firstLine.startsWith("#!");
        } catch (Exception e) {
            return false;
        }
    }

    private boolean hasLibraryStructure(Path srcDir) {
        try (Stream<Path> files = Files.list(srcDir)) {
            return files.anyMatch(file -> {
                String name = file.getFileName().toString().toLowerCase();
                return name.equals("index.js") || name.equals("index.ts") || 
                       name.equals("main.js") || name.equals("lib.js");
            });
        } catch (Exception e) {
            return false;
        }
    }

    private String readFileContent(Path file) {
        try {
            return Files.readString(file);
        } catch (Exception e) {
            return "";
        }
    }

    private String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        return dotIndex > 0 ? fileName.substring(dotIndex + 1) : "";
    }

    private boolean isCodeExtension(String extension) {
        Set<String> codeExtensions = Set.of("js", "ts", "jsx", "tsx", "py", "java", "go", "rs", "cpp", "c", "h", "cs");
        return codeExtensions.contains(extension);
    }

    /**
     * 项目特征数据类
     */
    private static class ProjectFeatures {
        int cliIndicators = 0;
        int libraryIndicators = 0;
        int applicationIndicators = 0;
        int devopsIndicators = 0;
        int developmentToolIndicators = 0;
        int documentationIndicators = 0;
        int configFileCount = 0;
        Map<String, Integer> fileTypes = new HashMap<>();
    }
} 